package com.cardone.platform.authority.util;

import com.cardone.common.template.util.TemplateUtils;
import com.cardone.context.ContextHolder;
import com.cardone.platform.authority.dto.NavigationDto;
import com.cardone.platform.authority.service.NavigationService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 导航工具类
 *
 * @author yaohaitao
 */
public class NavigationUtils {
    private NavigationUtils() {
    }

    /**
     * 生成面包屑
     *
     * @param navigationList 导航集合
     * @param navigation     导航
     * @return 面包屑
     */
    private static List<NavigationDto> buildBreadcrumb(final List<NavigationDto> navigationList, final NavigationDto navigation) {
        if (navigation == null) {
            return navigationList;
        }

        navigationList.add(0, navigation);

        return NavigationUtils.buildBreadcrumb(navigationList, navigation.getParentNavigation());
    }

    /**
     * 查询:导航
     *
     * @param navigationList 站代码
     * @param parentCode     导航代码
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListByParentCodeForTree(final List<NavigationDto> navigationList, final String parentCode) {
        if (CollectionUtils.isEmpty(navigationList)) {
            return Lists.newArrayList();
        }

        for (final NavigationDto navigation : navigationList) {
            if (StringUtils.equals(parentCode, navigation.getCode())) {
                if (CollectionUtils.isEmpty(navigation.getChilds())) {
                    return Lists.newArrayList();
                }

                return navigation.getChilds();
            }

            final List<NavigationDto> treeNavigationList = NavigationUtils.findListByParentCodeForTree(navigation.getChilds(), parentCode);

            if (!CollectionUtils.isEmpty(treeNavigationList)) {
                return treeNavigationList;
            }
        }

        return Lists.newArrayList();
    }

    /**
     * 查询:导航
     *
     * @param navigationList 站代码
     * @param parentId       导航标识
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListByParentIdForTree(final List<NavigationDto> navigationList, final String parentId) {
        if (CollectionUtils.isEmpty(navigationList)) {
            return Lists.newArrayList();
        }

        for (final NavigationDto navigation : navigationList) {
            if (StringUtils.equals(parentId, navigation.getId())) {
                if (CollectionUtils.isEmpty(navigation.getChilds())) {
                    return Lists.newArrayList();
                }

                return navigation.getChilds();
            }

            final List<NavigationDto> treeNavigationList = NavigationUtils.findListByParentIdForTree(navigation.getChilds(), parentId);

            if (!CollectionUtils.isEmpty(treeNavigationList)) {
                return treeNavigationList;
            }
        }

        return Lists.newArrayList();
    }

    /**
     * 查询:导航
     *
     * @param siteCode   站代码
     * @param parentCode 导航代码
     * @param level      层级
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListBySiteCodeAndParentCodeForTree(final String siteCode, final String parentCode, final int level) {
        return NavigationUtils.findListBySiteCodeAndTypeCodeAndParentCodeForTree(siteCode, null, parentCode, level);
    }

    /**
     * 查询:导航
     *
     * @param siteCode 站代码
     * @param parentId 导航标识
     * @param level    层级
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListBySiteCodeAndParentIdForTree(final String siteCode, final String parentId, final int level) {
        return NavigationUtils.findListBySiteCodeAndTypeCodeAndParentIdForTree(siteCode, null, parentId, level);
    }

    /**
     * 查询:导航
     *
     * @param siteCode   站代码
     * @param typeCode   类别代码
     * @param parentCode 导航代码
     * @param level      层级
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListBySiteCodeAndTypeCodeAndParentCodeForTree(final String siteCode, final String typeCode, final String parentCode, final int level) {
        final List<NavigationDto> navigationList = ContextHolder.getBean(NavigationService.class).findListByParentCodeForTree(siteCode, typeCode, parentCode, level);

        return NavigationUtils.process(navigationList);
    }

    /**
     * 查询:导航
     *
     * @param siteCode 站代码
     * @param typeCode 类别代码
     * @param parentId 导航标识
     * @param level    层级
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListBySiteCodeAndTypeCodeAndParentIdForTree(final String siteCode, final String typeCode, final String parentId, final int level) {
        final List<NavigationDto> navigationList = ContextHolder.getBean(NavigationService.class).findListByParentIdForTree(siteCode, typeCode, parentId, level);

        return NavigationUtils.process(navigationList);
    }

    /**
     * 查询:导航 T
     *
     * @param navigationList 站代码
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListForBreadcrumb(final List<NavigationDto> navigationList) {
        String requestUri = org.apache.commons.lang3.StringUtils.EMPTY;

        final javax.servlet.http.HttpServletRequest request = ContextHolder.getRequest();

        if (request != null) {
            requestUri = request.getRequestURI();
        }

        return NavigationUtils.findListForBreadcrumb(navigationList, requestUri);
    }

    /**
     * 查询:导航
     *
     * @param navigationList 站代码
     * @param href           导航链接
     * @return 导航对象集合
     */
    public static List<NavigationDto> findListForBreadcrumb(final List<NavigationDto> navigationList, final String href) {
        if (CollectionUtils.isEmpty(navigationList)) {
            return Lists.newArrayList();
        }

        for (final NavigationDto navigation : navigationList) {
            if (StringUtils.equals(href, navigation.getHref())) {
                return NavigationUtils.buildBreadcrumb(new ArrayList<>(), navigation);
            }

            final List<NavigationDto> breadcrumbNavigationList = NavigationUtils.findListForBreadcrumb(navigation.getChilds(), href);

            if (!CollectionUtils.isEmpty(breadcrumbNavigationList)) {
                return breadcrumbNavigationList;
            }
        }

        return Lists.newArrayList();
    }

    /**
     * 处理导航
     *
     * @param navigationList 导航集合
     * @return 导航集合
     */
    private static List<NavigationDto> process(final List<NavigationDto> navigationList) {
        if (CollectionUtils.isEmpty(navigationList)) {
            return navigationList;
        }

        final javax.servlet.http.HttpServletRequest request = ContextHolder.getRequest();

        java.util.Map<String, Object> model = Maps.newHashMap();

        if (request != null) {
            model.put("contextPath", request.getContextPath());
            model.put("requestURI", request.getRequestURI());
        }

        return NavigationUtils.process(navigationList, null, model);
    }

    /**
     * 处理导航
     *
     * @param navigationList   导航集合
     * @param parentNavigation 父级导航
     * @return 导航集合
     */
    private static List<NavigationDto> process(final List<NavigationDto> navigationList, final NavigationDto parentNavigation, java.util.Map<String, Object> model) {
        if (CollectionUtils.isEmpty(navigationList)) {
            return navigationList;
        }

        for (int i = navigationList.size() - 1; i >= 0; i--) {
            final NavigationDto navigation = navigationList.get(i);

            navigation.setParentNavigation(parentNavigation);

            String href = StringUtils.defaultString(navigation.getUrl(), navigation.getCode());

            String url = StringUtils.replace(href, "${contextPath}", "${contextPath!}");

            url = TemplateUtils.processString(url, Maps.newHashMap());

            if (!SecurityUtils.getSubject().isPermitted(url)) {
                navigationList.remove(i);

                continue;
            }

            href = TemplateUtils.processString(href, model);

            navigation.setHref(href);

            if (StringUtils.equals(href, org.apache.commons.collections.MapUtils.getString(model, "requestURI"))) {
                navigation.setActive(true);

                NavigationUtils.processParent(navigation);
            }

            if (!CollectionUtils.isEmpty(navigation.getChilds())) {
                NavigationUtils.process(navigation.getChilds(), navigation, model);
            }
        }

        return navigationList;
    }

    /**
     * 处理父级导航
     *
     * @param navigation 导航
     */
    private static void processParent(final NavigationDto navigation) {
        if (navigation.getParentNavigation() == null) {
            return;
        }

        navigation.getParentNavigation().setActive(true);

        NavigationUtils.processParent(navigation.getParentNavigation());
    }
}